import json
import re

from django import http
from django.core.cache import cache
from django.views import View

from apps.areas.models import Area, Address
from apps.users.models import Users
from utils import constants
from utils.response_code import RETCODE
from utils.views import LoginRequiredJSONMixin


class AreaView(View):
    """获取省市县"""

    def get(self, request):
        """接收前端传入的参数area_id"""

        area_id = request.GET.get('area_id')

        if not area_id:
            # 如果没有area_id，那么就是从省开始,此时需要提供省份的数据
            # 查询数据库需要try防止出错
            province_list = cache.get('province_list')  # 查询redis中是否有缓存
            # 如果没有缓存
            if not province_list:
                try:
                    province_models_list = Area.objects.filter(parent__isnull=True)

                    province_list = list()
                    for province in province_models_list:
                        province_list.append({'id': province.id, 'name': province.name})
                    # 加入缓存
                    cache.set('province_list', province_list, 3600)

                except Exception as e:
                    return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '数据查询错误'})

            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'province_list': province_list})
        else:
            sub_data = cache.get('sub_data_' + area_id)
            if not sub_data:

                # 如果存在area_id，说明是从市县开始 此时需要从数据库中查询出父id为area_id的数据
                try:
                    parent_model = Area.objects.get(id=area_id)
                    # 查询当前下的所有子数据
                    sub_models_list = parent_model.subs.all()
                    sub_list = list()
                    for sub_model in sub_models_list:
                        sub_list.append({'id': sub_model.id, 'name': sub_model.name})

                    sub_data = {
                        'id': parent_model.id,  # 父级pk
                        'name': parent_model.name,  # 父级name
                        'subs': sub_list  # 父级的子集
                    }
                    cache.set('sub_data_' + area_id, sub_data, 3600)

                except Exception as e:
                    return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '数据查询错误'})

            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'sub_data': sub_data})


class CreateAddressView(LoginRequiredJSONMixin, View):

    def post(self, request):
        """添加收货地址"""
        # 从数据库中查询该用户收货地址的数量
        count = request.user.addresses.count()
        # 判断地址是否超过20个最大限额
        if count >= constants.USER_ADDRESS_COUNTS_LIMIT:
            return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '超出收货地址上限'})
        # 获取前端写入的收货地址信息
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')  # 收货人
        province_id = json_dict.get('province_id')  # 收货省份id
        city_id = json_dict.get('city_id')  # 城市id
        district_id = json_dict.get('district_id')  # 县区id
        email = json_dict.get('email')  # 邮箱号
        mobile = json_dict.get('mobile')  # 手机号
        place = json_dict.get('place')  # 收货详细地址
        tel = json_dict.get('tel')  # 固定电话
        # title = json_dict.get("title")
        # print('----------------title:', title)
        # 校验参数
        if not all([receiver, province_id, city_id, district_id, mobile]):
            return http.HttpResponseBadRequest('缺少必传参数')

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('手机号不存在')
        if tel:
            # 如果传入固定电话就匹配一下
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseBadRequest('参数tel有误')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('参数email有误')
        # 保存一条用户收货地址
        try:
            address = Address.objects.create(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email,
            )
            # 设置默认地址
            if not request.user.default_address:
                # 将该地址设置为默认地址
                request.user.default_address = address
                request.user.save()

        except Exception as e:
            # logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '新增地址失败'})
        # 新增地址成功，将新增的地址响应给前端实现局部刷新
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        # 响应保存结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '新增地址成功', 'address': address_dict})


class UpdateAddressView(LoginRequiredJSONMixin, View):
    """更新收货地址"""

    @staticmethod
    def check_user(request, address_id):
        address = Address.objects.get(id=address_id)
        if not (address and address.user == request.user):
            return http.HttpResponseBadRequest('无效操作')

    def put(self, request, address_id):
        # 判断该收货地址是否属于该用户
        self.check_user(request, address_id)

        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')  # 收货人
        province_id = json_dict.get('province_id')  # 收货省份id
        city_id = json_dict.get('city_id')  # 城市id
        district_id = json_dict.get('district_id')  # 县区id
        email = json_dict.get('email')  # 邮箱号
        mobile = json_dict.get('mobile')  # 手机号
        place = json_dict.get('place')  # 收货详细地址
        tel = json_dict.get('tel')  # 固定电话

        if not all([receiver, province_id, city_id, district_id, mobile, place]):
            return http.HttpResponseBadRequest("参数错误")

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('手机号不存在')
        if tel:
            # 如果传入固定电话就匹配一下
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseBadRequest('参数tel有误')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('参数email有误')

        # 数据库进行更新
        try:
            # address = Address.objects.filter(id=address_id)
            # if address.title:
            # else:
            Address.objects.filter(id=address_id).update(
                user=request.user,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email
            )
        except Exception as e:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '更新异常'})

        # 从数据库提取数据并将数据提交给前端
        address = Address.objects.get(id=address_id)

        address_dict = {

            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '更新地址成功', 'address': address_dict})

    def delete(self, request, address_id):
        """删除收货地址"""
        self.check_user(request, address_id)

        try:
            address = Address.objects.get(id=address_id)
            # 进行逻辑删除
            address.is_deleted = True
            # 保存数据修改
            address.save()
        except:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '数据删除失败'})

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '删除成功'})


class DefaultAddressView(LoginRequiredJSONMixin, View):
    """设置默认收货地址"""

    def put(self, request, address_id):
        try:
            # 查询用户数据库
            user = Users.objects.get(id=request.user.id)
            # 修改该用户的默认收货地址
            user.default_address_id = address_id
            # 保存修改
            user.save()
        except:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '修改默认地址失败'})

        return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '默认收货地址修改成功'})


class UpdateAddressTitleView(LoginRequiredJSONMixin, View):
    def put(self, request, address_id):
        """接收参数"""

        json_dict = json.loads(request.body.decode())
        title = json_dict.get('title')
        try:
            # 获取当前收货地址
            address = Address.objects.get(id=address_id)
            # 修改标题
            address.title = title
            # 保存修改操作
            address.save()
        except:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '修改标题错误'})

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '修改成功'})
